package com.lmb.todo.controller;

import com.lmb.todo.pojo.Folder;
import com.lmb.todo.pojo.Group;
import com.lmb.todo.pojo.RegisterBody;
import com.lmb.todo.pojo.User;
import com.lmb.todo.pojo.resp.Code;
import com.lmb.todo.pojo.resp.CommonResp;
import com.lmb.todo.service.FolderService;
import com.lmb.todo.service.GroupService;
import com.lmb.todo.service.impl.UserServiceImpl;
import com.lmb.todo.utils.AuthUtil;
import com.lmb.todo.utils.Constant;
import com.lmb.todo.utils.JwtUtil;
import com.lmb.todo.utils.StringUtil;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lmb
 */
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private FolderService folderService;

    @Autowired
    private GroupService groupService;

    @Autowired
    private AuthUtil authUtil;

    /**
     * 获取用户信息
     * @param id Integer
     * @return CommonResp
     */
    @GetMapping("/{id}")
    public CommonResp getById(@PathVariable Integer id) {
        User user = userService.getById(id);
        return new CommonResp(
            user,
            user != null ? Code.HTTP_SUCCESS : Code.HTTP_FAILED,
            user != null ? "success" : "failed"
        );
    }

    /**
     * 注册
     * @param user User
     */
    @PostMapping("")
    public CommonResp register(@RequestBody RegisterBody user){
        CommonResp resp = new CommonResp();
        String username = user.getUsername();
        String password = user.getPassword();
        String dPassword = user.getdPassword();

        if (!password.equals(dPassword)) {
            resp.setCode(Code.C_D_PASSWORD_ERROR);
            resp.setMsg("The two passwords are different.");
            return resp;
        }

        if (!StringUtil.checkUsername(username) || !StringUtil.checkPassword(password)) {
            // 用户名和密码校验不成功
            resp.setCode(Code.C_USERNAME_PASSWORD_ERROR);
            resp.setMsg("The username or password format is incorrect.Please check and try again!");
            return resp;
        }

        User sameUsernameUser = userService.getByUsername(username);
        if (sameUsernameUser != null) {
            resp.setCode(Code.C_USERNAME_REPETITION);
            resp.setMsg("The same username already exists.Please change the username!");
            return resp;
        }

        int countRow = userService.add(user);
        if (countRow > 0) {
            // 注册成功
            resp.setCode(Code.HTTP_SUCCESS);
            resp.setMsg("Registration succeeded. Please log in.");
            return resp;
        }

        // 注册失败
        resp.setCode(Code.S_UNKNOWN_ERROR);
        resp.setMsg("Network is busy. Please try again later.");
        return resp;
    }

    /**
     * 登录
     * @param username String
     * @param password String
     */
    @PostMapping("/login")
    public CommonResp login(@RequestParam String username, @RequestParam String password) {
        Map<String, Object> data = new HashMap<>(2);
        User user = userService.getByUsernameAndPassword(username, password);

        if (user == null) {
            return new CommonResp(
                null,
                Code.C_USERNAME_PASSWORD_ERROR,
                "The username or password is incorrect. Please check and try again!"
            );
        }

        // 登录成功，调用认证方法返回 token 信息
        data.put(Constant.TODOAUTH, authUtil.auth(user));
        user.setPassword(null);
        user.setId(null);
        data.put("userInfo", user);
        return new CommonResp(data, Code.HTTP_SUCCESS, "success");
    }

    /**
     * 判断 token 是否过期
     */
    @GetMapping("/c")
    public CommonResp checkToken(@CookieValue(name = "todoAuth", required = false) String token, HttpServletRequest req) {
        Map<String, Object> data = new HashMap<>(2);
        CommonResp resp = new CommonResp();
        boolean isTokenEffective = JwtUtil.checkToken(token, req);

        if (token == null || "".equals(token) || !isTokenEffective) {
            data.put("userInfo", null);
            data.put("expired", true);
            resp.setData(data);
            resp.setCode(Code.C_TOKEN_EXPIRED);
            resp.setMsg("The authentication has expired. Please login again!");
            return resp;
        }

        Claims claims = JwtUtil.parse(token);
        Integer userId = (Integer)claims.get("userId");
        User user = userService.getById(userId);
        data.put("userInfo", user);
        data.put("expired", false);
        resp.setData(data);
        resp.setCode(Code.HTTP_SUCCESS);
        resp.setMsg("ok!");
        return resp;
    }


    /**
     * 获取用户的分组和文件夹数据
     */
    @GetMapping("")
    public CommonResp getGroupAndFolder() {
        HashMap userInfo = authUtil.getAuthUserInfo();
        Integer userId = (Integer) userInfo.get("userId");

        List<Folder> folderList = folderService.getAllByUserId(userId);
        List<Group> groupList = groupService.getAllByUserId(userId);

        Map<String, Object> data = new HashMap<>(2);
        data.put("folders", folderList);
        data.put("groups", groupList);

        return new CommonResp(
            data,
            Code.HTTP_SUCCESS,
            "ok!"
        );
    }

    /**
     * 认证错误，用户未登录返回未认证成功消息
     * @param req HttpServletRequest
     * @param resp HttpServletResponse
     */
    @RequestMapping("/error")
    public CommonResp error(HttpServletRequest req, HttpServletResponse resp) {
        resp.setStatus(Code.HTTP_FAILED);
        return new CommonResp(
            null,
            Code.C_UNAUTHORIZED,
            "Unauthorized!"
        );
    }

}
